/*******************************************************************************
**                                                                            **
** Copyright (C)    (2016)                                               **
**                                                                            **
** All rights reserved.                                                       **
**                                                                            **
** This document contains proprietary information belonging to .         **
** Passing on and copying of this document, and communication                 **
** of its contents is not permitted without prior written authorization.      **
**                                                                            **
********************************************************************************
**                                                                            **
**  FILENAME    : Xcp_Cal.c                                                   **
**                                                                            **
**  Created on  :                                                             **
**  Author      : qinchun.yang                                                **
**  Vendor      :                                                             **
**  DESCRIPTION : Implementation of the XCP_Cal command			              **
**                                                                            **
**  SPECIFICATION(S) :   AUTOSAR classic Platform 4.2.2                       **
**                                                                            **
*******************************************************************************/
/*=======[V E R S I O N  I N F O R M A T I O N]===============================*/

#define XCP_CAL_C_AR_MAJOR_VERSION  4u
#define XCP_CAL_C_AR_MINOR_VERSION  2u
#define XCP_CAL_C_AR_PATCH_VERSION  2u
#define XCP_CAL_C_SW_MAJOR_VERSION  1u
#define XCP_CAL_C_SW_MINOR_VERSION  0u
#define XCP_CAL_C_SW_PATCH_VERSION  0u

/*=======[I N C L U D E S]====================================================*/
//#include "Xcp_Regs.h"
#include "Xcp_Internal.h"
/*=======[V E R S I O N  C H E C K]===========================================*/
#if (XCP_CAL_C_AR_MAJOR_VERSION != XCP_H_AR_MAJOR_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif
#if (XCP_CAL_C_AR_MINOR_VERSION != XCP_H_AR_MINOR_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif
#if (XCP_CAL_C_AR_PATCH_VERSION != XCP_H_AR_PATCH_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif
#if (XCP_CAL_C_SW_MAJOR_VERSION != XCP_H_SW_MAJOR_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif
#if (XCP_CAL_C_SW_MINOR_VERSION != XCP_H_SW_MINOR_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif
#if (XCP_CAL_C_SW_PATCH_VERSION != XCP_H_SW_PATCH_VERSION)
  #error "Xcp_Cal.c : Mismatch in Specification Major Version"
#endif

#if (XCP_PL_CAL == (XCP_PL_CAL & XCP_RESOURCE))
/*=======[M A C R O S]========================================================*/
#define XCP_MODIFY_BITS_MAX_S   32
#define XCP_SET_PAG_MODE_ALL    0x83u
#define XCP_SET_PAG_MODE_ECU    0x01u
#define XCP_SET_PAG_MODE_XCP    0x02u

#define XCP_GET_PAG_MODE_ECU    0x01u
#define XCP_GET_PAG_MODE_XCP    0x02u

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/
static FUNC(void, XCP_CODE)Xcp_DownloadHal(void);
static FUNC(void, XCP_CODE)Xcp_SwitchToWP(void);
static FUNC(void, XCP_CODE)Xcp_SwitchToRP(void);
static FUNC(void, XCP_CODE) Xcp_SetCalPageHal(void);
/*=======[F U N C T I O N   I M P L E M E N T A T I O N S]====================*/

#if (XCP_SET_REQUEST == STD_ON)
#if (XCP_STORE_CAL == STD_ON)
FUNC(void, XCP_CODE)
XCP_DoStoreCAL(void)
{
	if(XCP_SESSION_STATE_STORE_CAL == (XCP_SESSION_STATE_STORE_CAL & Xcp_SessionStatus))
	{
		if(E_OK == Xcp_NvramWriteCal())
		{
			Xcp_SessionStatus &= (~XCP_SESSION_STATE_STORE_CAL);
		}
		else
		{
			Xcp_SetErrorCode(XCP_ERR_WRITE_PROTECTED);
			Xcp_RespLength = 0x02u;
		}
	}
}
#endif
#endif
/******************************************************************************/
/*
 * @brief               <Calibration Initialization>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/

FUNC(Std_ReturnType, XCP_CODE)
Xcp_CALInit(void)
{
	uint8 segNum = 0;
	#if (XCP_PAG_SUPPORT == STD_ON)
	#if (XCP_MMU_SUPPORT == STD_ON)
	/* To do something about MMU initial */
	Xcp_MmuInit();
	#elif(XCP_OVC_SUPPORT == STD_ON)
	/* To do something about Overlay initial */
	Xcp_VocInit();
	#endif
	#endif
    /* init the RAM page */
    for (segNum = 0; segNum < Xcp_SegmentInfo.maxSegNum; segNum++)
    {
        Xcp_CalBufferCopy(Xcp_SegmentInfo.pageInfoPtr[segNum].romStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].ramStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].size);
		#if (STD_ON == XCP_PAG_SUPPORT)
		#if (STD_ON == XCP_SWITCH_PAG_SUPPORT)
        #if ((STD_OFF == XCP_MMU_SUPPORT) && (STD_OFF == XCP_OVL_SUPPORT))
        /* alloc an array to copy the data in the RAM */
        Xcp_CalBufferCopy(Xcp_SegmentInfo.pageInfoPtr[segNum].ramStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].bufferPtr,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].size);
        #endif
		#endif
        Xcp_ActivPagNum[segNum] = XCP_RAM_PAGE_NUM;
		#endif
    }
	return E_OK;
}

/******************************************************************************/
/*
 * @brief               <Command Download Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE)
Xcp_Download(void)
{
    /* check frame length */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if (
		#if (XCP_ADDRESS_GRANULARITY != XCP_AG_DWORD)
		(Xcp_CmdLength != (2u +(Xcp_CmdBuffer[1u] * XCP_AG)))
		#else
		(Xcp_CmdLength != (4u +(Xcp_CmdBuffer[1u] * XCP_AG)))
		#endif
		&& (Xcp_CmdLength != XCP_CAN_MAX_DLC)
    	)
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else if ((Xcp_CmdBuffer[1u] > XCP_DOWNLOAD_SIZE)
    || (0u == Xcp_CmdBuffer[1u]))
    {
        Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        Xcp_DownloadHal();
    }
    Xcp_SendResp();
    return;
}
static FUNC(void, XCP_CODE)
Xcp_DownloadHal(void)
{
    uint8 pos = 0;
    uint8 numOfElements = Xcp_CmdBuffer[1u];
    P2VAR(Xcp_AGType, AUTOMATIC, XCP_VAR) sourPtr;
    P2VAR(Xcp_AGType, AUTOMATIC, XCP_VAR) destPtr;
    uint32 u4DestAddr  = Xcp_Mta2Ptr(Xcp_MTA.extensionAddr,Xcp_MTA.transferAddr);

    if (FALSE == Xcp_CheckAddress(u4DestAddr, (numOfElements*XCP_AG), XCP_MEM_CAL_RAM))
    {
        if (TRUE == Xcp_CheckAddress(u4DestAddr, (numOfElements*XCP_AG), XCP_MEM_CAL_ROM))
        {
            Xcp_SetErrorCode(XCP_ERR_WRITE_PROTECTED);
            Xcp_RespLength = 0x02u;
        }
        else
        {
            Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
            Xcp_RespLength = 0x02u;
        }
    }
    else
    {
        /* write the data of CRO to destination address. */
        sourPtr = (Xcp_AGType*)&Xcp_CmdBuffer[XCP_DOWNLOAD_DATA_OFFSET];
        destPtr = (Xcp_AGType*)u4DestAddr;
        for (pos = 0u; pos < numOfElements; pos++)
        {
            destPtr[pos] = sourPtr[pos];
        }
        /*updata the MTA*/
        Xcp_UpdateMTA(numOfElements*XCP_AG);
    }
    return;
}
/*
 * CAL/PAG Optional Function
 */
#if (XCP_DOWNLOAD_NEXT == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command DownloadNext Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE)
Xcp_DownloadNext(void)
{
    uint8 pos = 0;
    Xcp_AGType * sourPtr;
    Xcp_AGType * destPtr;
    uint32 u4DestAddr  = Xcp_Mta2Ptr(Xcp_MTA.extensionAddr,Xcp_MTA.transferAddr);

    /* check frame length has been checked before */
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else if (FALSE == Xcp_CheckAddress(u4DestAddr, (Xcp_BlockBufferLen*XCP_AG), XCP_MEM_CAL_RAM))
    {
        if (TRUE == Xcp_CheckAddress(u4DestAddr, (Xcp_BlockBufferLen*XCP_AG), XCP_MEM_CAL_ROM))
        {
            Xcp_SetErrorCode(XCP_ERR_WRITE_PROTECTED);
            Xcp_RespLength = 0x02u;
        }
        else
        {
            Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
            Xcp_RespLength = 0x02u;
        }
    }
    else
    {
        /* write the data in BlockBuffer to destination address. */
        sourPtr = &Xcp_BlockBuffer[0u];
        destPtr = (Xcp_AGType*)u4DestAddr;
        for (pos = 0u; pos < Xcp_BlockBufferLen; pos++)
        {
            destPtr[pos] = sourPtr[pos];
        }
        /*updata the MTA*/
        Xcp_UpdateMTA(Xcp_BlockBufferLen*XCP_AG);
    }
    Xcp_SendResp();
    return;
}
#endif
#if (XCP_DOWNLOAD_MAX == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command DownloadMax Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_DownloadMax(void)
{
    uint8 pos = 0;
    Xcp_AGType * sourPtr;
    Xcp_AGType * destPtr;
    uint32 u4DestAddr  = Xcp_Mta2Ptr(Xcp_MTA.extensionAddr,Xcp_MTA.transferAddr);

    /* check frame length */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    /* caution: if the bus interface is not CAN the length check here shall be modified */
    if (Xcp_CmdLength != XCP_CAN_MAX_DLC)
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else if (FALSE == Xcp_CheckAddress(u4DestAddr, (XCP_DOWNLOADMAX_SIZE*XCP_AG), XCP_MEM_CAL_RAM))
    {
        if (TRUE == Xcp_CheckAddress(u4DestAddr, (XCP_DOWNLOADMAX_SIZE*XCP_AG), XCP_MEM_CAL_ROM))
        {
            Xcp_SetErrorCode(XCP_ERR_WRITE_PROTECTED);
            Xcp_RespLength = 0x02u;
        }
        else
        {
            Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
            Xcp_RespLength = 0x02u;
        }
    }
    else
    {
        /* write the data of CRO to destination address. */
        sourPtr = (Xcp_AGType*)&Xcp_CmdBuffer[XCP_AG];
        destPtr = (Xcp_AGType*)u4DestAddr;
        for (pos = 0u; pos < XCP_DOWNLOADMAX_SIZE; pos++)
        {
            destPtr[pos] = sourPtr[pos];
        }
        /*updata the MTA*/
        Xcp_UpdateMTA(XCP_DOWNLOADMAX_SIZE*XCP_AG);
    }
    Xcp_SendResp();
    return;
}
#endif

/*
 * SHORT_DOWNLOAD CMD:don't support in CAN
 * */



#if (XCP_MODIFY_BITS == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command ModifyBits Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_ModifyBits(void)
{
    uint8 shiftValue = Xcp_CmdBuffer[1u];
    uint16 andMask = 0;
    uint16 xorMask = 0;
    uint32 u4SourceAddr = Xcp_Mta2Ptr(Xcp_MTA.extensionAddr,Xcp_MTA.transferAddr);

    /* check frame length */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 0x06u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else if (FALSE == Xcp_CheckAddress(u4SourceAddr, sizeof(uint32), XCP_MEM_CAL_RAM))
    {
        if (TRUE == Xcp_CheckAddress(u4SourceAddr, sizeof(uint32), XCP_MEM_CAL_ROM))
        {
            Xcp_SetErrorCode(XCP_ERR_WRITE_PROTECTED);
            Xcp_RespLength = 0x02u;
        }
        else
        {
            Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
            Xcp_RespLength = 0x02u;
        }
    }
    else if (shiftValue >= XCP_MODIFY_BITS_MAX_S)
    {
        Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        /* get infomation from the frame */
        Xcp_CopyU1BufferToU2(&Xcp_CmdBuffer[2], &andMask, CPU_BYTE_ORDER);
        Xcp_CopyU1BufferToU2(&Xcp_CmdBuffer[4], &xorMask, CPU_BYTE_ORDER);
        /* do modify */
        *(uint32*)u4SourceAddr &= (~((uint32)(((uint16)~andMask) << shiftValue)));
        *(uint32*)u4SourceAddr ^= ((uint32)(xorMask << shiftValue));
        /* Do not updata the MTA*/
    }
    Xcp_SendResp();
    return;
}
#endif

/*
 * PAG
 */
#if (STD_ON == XCP_PAG_SUPPORT)
/******************************************************************************/
/*
 * @brief               <Switching Page to RAM>
 *
 * <Switch Page to RAM by using Buffer> .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
static FUNC(void, XCP_CODE)
Xcp_SwitchToWP(void)
{
    uint8 segNum = 0;
    for (segNum = 0; segNum < Xcp_SegmentInfo.maxSegNum; segNum++)
    {
		#if ((STD_ON == XCP_SWITCH_PAG_SUPPORT)\
		&&  (STD_OFF == XCP_MMU_SUPPORT)\
		&& (STD_OFF == XCP_OVC_SUPPORT))
        Xcp_CalBufferCopy(Xcp_SegmentInfo.pageInfoPtr[segNum].bufferPtr,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].ramStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].size);
		#endif
        Xcp_ActivPagNum[segNum] = XCP_RAM_PAGE_NUM;
    }
	return;
}

/******************************************************************************/
/*
 * @brief               <Switching Page to FLASH>
 *
 * <Switch Page to FLASH by using Buffer> .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
static FUNC(void, XCP_CODE)
Xcp_SwitchToRP(void)
{
    uint8 segNum = 0;
    for (segNum = 0; segNum < Xcp_SegmentInfo.maxSegNum; segNum++)
    {
		#if ((STD_ON == XCP_SWITCH_PAG_SUPPORT)\
				&&  (STD_OFF == XCP_MMU_SUPPORT)\
				&& (STD_OFF == XCP_OVC_SUPPORT))
        Xcp_CalBufferCopy(Xcp_SegmentInfo.pageInfoPtr[segNum].ramStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].bufferPtr,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].size);
        Xcp_CalBufferCopy(Xcp_SegmentInfo.pageInfoPtr[segNum].romStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].ramStart,
                          Xcp_SegmentInfo.pageInfoPtr[segNum].size);
		#endif
        Xcp_ActivPagNum[segNum] = XCP_FLASH_PAGE_NUM;
    }
	return;
}

#if (STD_ON == XCP_SET_CAL_PAGE)
/******************************************************************************/
/*
 * @brief               <Command SetCalPage Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE)
Xcp_SetCalPage(void)
{
    /* check frame length */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 0x04u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    /* according to the solution of CANape, page switching shall
     * be excuted only in 0x83 mode.
     */
    else
    {
        Xcp_SetCalPageHal();
    }
    Xcp_SendResp();
    return;
}

static FUNC(void, XCP_CODE)
Xcp_SetCalPageHal(void)
{
    uint8 mode = Xcp_CmdBuffer[1u];
    uint8 segNum = Xcp_CmdBuffer[2u];
    uint8 pagNum = Xcp_CmdBuffer[3u];

    if (mode != XCP_SET_PAG_MODE_ALL)
    {
        Xcp_SetErrorCode(XCP_ERR_MODE_NOT_VALID);
        Xcp_RespLength = 0x02u;
    }
    else if (segNum >= Xcp_SegmentInfo.maxSegNum)
    {
        Xcp_SetErrorCode(XCP_ERR_SEGMENT_NOT_VALID);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        if (Xcp_ActivPagNum[segNum] != pagNum)
        {
            switch (pagNum)
            {
                case XCP_FLASH_PAGE_NUM:
                {
                    Xcp_SwitchToRP();
                    break;
                }
                case XCP_RAM_PAGE_NUM:
                {
                    Xcp_SwitchToWP();
                    break;
                }
                default:
                {
                    Xcp_SetErrorCode(XCP_ERR_PAGE_NOT_VALID);
                    Xcp_RespLength = 0x02u;
                    break;
                }
            }
        }
    }
    return;
}

#endif /* (STD_ON == XCP_SET_CAL_PAGE) */
#if (XCP_GET_CAL_PAGE == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command getCalPage Handler>
 *
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_GetCalPage(void)
{
    uint8 accessMode = Xcp_CmdBuffer[1u];
    uint8 segNum = Xcp_CmdBuffer[2u];
    /* check frame length */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 0x03u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check pgm active status */
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    /* check protection status */
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else if (segNum >= Xcp_SegmentInfo.maxSegNum)
    {
        Xcp_SetErrorCode(XCP_ERR_SEGMENT_NOT_VALID);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        switch(accessMode)
        {
            case XCP_GET_PAG_MODE_ECU:
            case XCP_GET_PAG_MODE_XCP:
            {
                Xcp_RespBuffer[3u] = Xcp_ActivPagNum[segNum];
                Xcp_RespLength = 4;
                break;
            }
            default:
            {
                Xcp_SetErrorCode(XCP_ERR_MODE_NOT_VALID);
                Xcp_RespLength = 0x02u;
                break;
            }
        }
    }
    Xcp_SendResp();
    return;
}
#endif /* (XCP_GET_CAL_PAGE == STD_ON) */
#endif /* (STD_ON == XCP_PAG_SUPPORT) */

#endif /* #if (XCP_PL_CAL == (XCP_PL_CAL & XCP_RESOURCE)) */
